﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;  //usado para administrar los hilos
using System.Collections;  //usado para ArrayList

using SistemaCenterQuimPost.Entidad;  //Usado para instanciar objetos de clase Producto y agilizar el filtrado de descripción.
using System.Text.RegularExpressions; //usado para expresiones regulares. Filtrar descripciones
using SistemaCenterQuimPost.Control; //usado para validar datos.
using SistemaCenterQuimPost.Plantillas; //necesario para obtener fecha, nombre usuario etc,

using System.IO;    //3 referencias que son necesarias para el proceso de archivos.
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;



namespace SistemaCenterQuimCentral.UI.CentralAdministrador
{
    public partial class frmActualizarPreciosCentral : SistemaCenterQuimPost.Plantillas.frmPlantillaHijo
    {
               //-------------------ATRIBUTOS--------------------------------------------------------

        //(ALE)COLOCAR BIEN ESTAS 2 INSTRUCCIONES SI ES QUE NO LO ESTÁN. 
        private DataSet3 centerQuimDs;  //Atributos usados para obtener datos de la base de datos.   

        private DataSet3TableAdapters.ProductosTableAdapter productosTa;

        private bool refrescarResgProductos; //La primera vez debe refrescar el resgProductos.

        private ArrayList resgProductos; // colección usada para guardar Codigos de productos y descripción, se tiene una pequeña base de dato para realizar las busqueda mediante filtros más rapidamente.

        private Thread oHiloActualizarResgProductos; //hilos que son ejecutados concurrentemente con la aplicación.
        private Thread oHiloFiltrarDescripcion;

        private string estadoDelFormulario;

        //objeto para serializar los RegistroUsuario y RegistroListaPrecio en formato binario
        private BinaryFormatter aplicadorFormato = new BinaryFormatter(); //Clase que permite serializar objeto, es decir pasarlo a binario.
        private FileStream listaPreciosSalida; //clase que maneja la información sobre el archvi y la forma de crearlo.
        

        //------------------CONSTRUCTORES---------------------------------------------------------------------

        public frmActualizarPreciosCentral()  //este constructor es llamado desde frmGestionProductosA
        {
            InitializeComponent();

            estadoDelFormulario = "";

            refrescarResgProductos = true; //inicializamos a true, ya que la primera vez que trate de usar ResgProductos tendra que actualizar.

            //(ALE) COLOCAR BIEN ESTAS 2 INSTRUCCIONES SI ES QUE NO LO ESTÁN
            this.centerQuimDs = new DataSet3();

            this.productosTa = new DataSet3TableAdapters.ProductosTableAdapter();
            
            this.resgProductos = new ArrayList();  //se inicializa la colección ArrayList que guardará una base de datos parcial.          
            
            this.oHiloActualizarResgProductos = new Thread(new ThreadStart(actualizarResgProductos)); //Instancia el hilo y lo delega al metodo actualizarResgProductos. 
            this.oHiloFiltrarDescripcion = new Thread(new ThreadStart(filtrarDescripcion));

        }

        

        //-----------------ESTADOS-------------------------------------------------------------

        protected virtual void frmActualzarPreciosCentral_Load(object sender, EventArgs e)
        {
            CheckForIllegalCrossThreadCalls = false;  //necesario para trabajar con hilos.

            estEsperandoOperacion(); //estado al comenzar el formulario o al fracasar en la busqueda.

        }

        //virtual me permite redefinir, en este caso solo en las clases hijas
        protected virtual void estEsperandoOperacion() //estado luego de realizar una busqueda exitosa, agregar o editar. Es decir con datos en vista.
        {
                System.Windows.Forms.Control[] controlesHabilitados = { this.txtCodBarra, this.btnBusCodigo, this.txtDescripcion, this.btnBusDescripcion, this.btnProcesar};
                System.Windows.Forms.Control[] controlesDeshabilitados = { this.lstProductosCodBarra, this.lstProductosDescripcion};
                System.Windows.Forms.Control[] controlesVisibles = { };
                System.Windows.Forms.Control[] controlesInvisibles = { this.lstProductosCodBarra, this.lstProductosDescripcion, lblError };

                habilitarControles(controlesHabilitados);
                deshabilitarControles(controlesDeshabilitados);
                visibleControles(controlesVisibles);
                invisibleControles(controlesInvisibles);

                if (refrescarResgProductos) //si hace falta actualizar el refrescarResgProducto se realiza
                {
                    ejecutarHiloActualizarResgProductos();

                }

            errorProvider1.Clear();  //se borran los errores, si habian.

            txtCodBarra.Focus();   //se deja el foco en txtCodBarra

            estadoDelFormulario = "estEsperandoOperacion";
        }

       

        //--------------------METODOS VARIOS--------------------------------------------------------------------------------

        protected virtual void vaciarTextBox() //Se deja en blanco todos los textBox, usado en estados estInicial y estAgregar.
        {
            txtCodBarra.Text = "";
            txtDescripcion.Text = "";
            dgvProductos.Rows.Clear();
        }

        //Virtual, permite redefinir en frmAltaProductosDisueltos y frmRecibirProductos
        protected virtual void actualizarResgProductos() //Se refresca el arrayList resgProductos
        {
            try
            {
                //(ALE) HACER EL FILL O COMO LO LLAMES ACA ABAJO
                //ProductosTa.FillByProductos1(centerQuimDs,...);
                productosTa.Fill(centerQuimDs.Productos);

                resgProductos.Clear(); //Se vacia resgProductos (ArrayList)

                foreach (DataRow unaFila in centerQuimDs.Productos) //Se recorre todas las filas  del centerQuimDs.Productos y se cargan los productos al ArrayList
                {
                    resgProductos.Add(new Producto(Convert.ToString(unaFila[0]), Convert.ToString(unaFila[3])));
                }

                refrescarResgProductos = false;

            }
            catch (IndexOutOfRangeException)
            {
                //si llega a ocurrir esta excepcion no se tiene en cuenta. Podría no haber productos cargados y lanzaría esta excepción.

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }

        }

        protected void btnBusCodigo_Click(object sender, EventArgs e)  //método que se ejecuta cuando se presiona sobre el botón btnBusCodigo
        {
            eventoBusCodigo();

        }

        protected virtual void eventoBusCodigo()  //Se encapsula en un método para que pueda usar cuando se presiona Enter sobre el txtCodBarra en estado de busqueda o click en btnBusCodBarra.
        {

            //no hace falta que pregunte si txtCodBarra es blanco, ya que por la forma de filtrar no encontrará nada igual.                                

            if (refrescarResgProductos)   //si es necesario actualizar el resgProductos se lo hace sino no
            {
                ejecutarHiloActualizarResgProductos();  //ejecuta el hilo que actualiza el ResgProductos
            }

            filtrarCodigoBarra();


            if (lstProductosCodBarra.Items.Count == 0)  //el filtro no obtuvo coincidencias.
            {
                //Se informa que no se encontró nada 
                MessageBox.Show("Su consulta no ha arrojado resultados.", "INFORME", MessageBoxButtons.OK, MessageBoxIcon.Information);

                //Como no encontró nada se deja en este estado.
                this.estEsperandoOperacion();
            }
            else
            {
                if (lstProductosCodBarra.Items.Count == 1)   //solo se encontró una sola coincidencia. No es necesario mostrar el lstProductosCodBarra. Directamente se muestra el producto.
                {
                    this.estadoDelFormulario = "Buscando";  //Se coloca este estado ya que si encuentra algo, cargará el txtDescripcion y lanzará el evento TextChanged()

                    cargarProductoPorCodigo(this.txtCodBarra.Text.Trim());  //busca producto con codigo de barra único (una coincidencia) encontrado en el oHiloFiltrarCodBarra y lo carga en los textBox.

                    estEsperandoOperacion(); //se deja en el estado necesario

                }
                else
                {
                    //si se obtuvo más de una coincidencia, solo se muestran éstas en lstProductosCodBarra, y espera a que el usuario seleccione una.

                    lstProductosCodBarra.Visible = true;
                    lstProductosCodBarra.Enabled = true;

                    //lstProductosCodBarra.Focus(); //se deja el foco en el dgvProductosCodBarra para que elija alguna coincidencia.

                    //lstProductosCodBarra.SelectedIndex=0;  //se deja seleccionado el primer items.
                }

            }

        }

        protected void ejecutarHiloActualizarResgProductos() // hilo para actualizar el atributo ResgProductos
        {
            if ((oHiloActualizarResgProductos.ThreadState == ThreadState.Unstarted) || (oHiloActualizarResgProductos.ThreadState == ThreadState.Stopped))
            {
                this.oHiloActualizarResgProductos = new Thread(new ThreadStart(actualizarResgProductos));
                this.oHiloActualizarResgProductos.Priority = ThreadPriority.Highest;
                this.oHiloActualizarResgProductos.Start();  //Se ejecuta el hilo para actualizar el atributo ResgProductos
            }
        }



        protected virtual void cargarProductoPorCodigo(string unCodBarra) //busca producto con codigo de barra único (una coincidencia) encontrado en el oHiloFiltrarCodBarra y lo carga en los textBox.
        {
            try
            {
                //(ALE)HACER EL FILL O COMO LO LLAMES ACA ABAJO
                //ProductosTa.FillByProductos1(centerQuimDs,unCodBarra);
                productosTa.FillByCodigo(centerQuimDs.Productos, unCodBarra);

                //ARREGLAR ESTO. Se rellena los textBox con la consulta encontrada. 
                dgvProductos.Rows.Add(centerQuimDs.Productos[0].codProducto, centerQuimDs.Productos[0].descripcion, centerQuimDs.Productos[0].precioCosto, centerQuimDs.Productos[0].precioVenta, centerQuimDs.Productos[0].fechaActualización.ToString("d"));
                

                //...
                //..FALTAN LOS OTROS. ACORDATE QUE ESTE ES EL DE CAJERO, TIENE POCOS CONTROLES.

            }
            catch (IndexOutOfRangeException)
            {

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }
        }

        protected void filtrarCodigoBarra()  //Filtra y carga las descripciones (si las hay) en el lstProductos. Método que se ejecuta dentro de un hilo. 
        {

            this.oHiloActualizarResgProductos.Join(); //espera a que primero termine el oHiloActualizarResgProductos para proceder con el actual.

            lstProductosCodBarra.Items.Clear(); //vaciamos el lstProductosCodBarra por si tuviera descripciones anteriores.


            foreach (Producto unProducto in resgProductos) //buscamos las descripciones asociadas al código y la cargamos en el lstProductosCodBarra
            {
                if (this.txtCodBarra.Text.Trim() == unProducto.CodBarra)
                {
                    lstProductosCodBarra.Items.Add(unProducto.Descripcion);
                }

            }

        }

        protected void lstProductosCodBarra_DoubleClick(object sender, EventArgs e)  //captura en evento doble click sobre lstProductosCodBarra
        {
            procesarEleccionLstProductosCodBarra();
        }

        protected void procesarEleccionLstProductosCodBarra()  //se encapsulo para que se pueda usar con DoubleClick y Enter sobre el lstProductosCodBarra
        {
            try
            {
                this.estadoDelFormulario = "Buscando";  //Se coloca este estado ya que si encuentra algo, cargará el txtDescripcion y lanzará el evento TextChanged()

                cargarProductoPorDescripcion(lstProductosCodBarra.SelectedItem.ToString()); //busca producto por descripción en la base de datos, y lo carga en los textBox.

                estEsperandoOperacion(); //se deja en el estado necesario

            }
            catch (IndexOutOfRangeException)
            {

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }
        }

        protected virtual void cargarProductoPorDescripcion(string unaDescripcion)  //busca el producto por descripción en la base de datos y lo carga en los textbox.
        {
            //(ALE) HACER EL FILL O COMO LO LLAMES ACA ABAJO
            productosTa.FillByNombre(centerQuimDs.Productos, unaDescripcion);

            //ARREGLAR ESTO. Se rellena los textBox con la consulta encontrada. 
            //ARREGLAR ESTO. Se rellena los textBox con la consulta encontrada. 
            dgvProductos.Rows.Add(centerQuimDs.Productos[0].codProducto, centerQuimDs.Productos[0].descripcion, centerQuimDs.Productos[0].precioCosto, centerQuimDs.Productos[0].precioVenta, centerQuimDs.Productos[0].fechaActualización.ToString("d"));
                
            //..
            //...
            //..FALTAN LOS OTROS. ACORDATE QUE ESTE ES EL DE CAJERO, TIENE POCOS CONTROLES.

        }

        protected void txtCodBarra_KeyDown(object sender, KeyEventArgs e)  //captura el evento KeyDown sobre el txtCodBarra.
        {
            if (e.KeyCode == Keys.Enter)
            {
                if (estadoDelFormulario == "estEsperandoOperacion") //estado esperando operación o estado inicial
                {
                    eventoBusCodigo();

                }

            }
            else
            {
                if ((e.KeyCode == Keys.Down) & (lstProductosCodBarra.Items.Count > 0) & (estadoDelFormulario == "estEsperandoOperacion")) //Si se presiona para abajo y tiene a lstProductosDescripcion visible (es decir se encuentra esperando operacion y con items en la lista)
                {

                    lstProductosCodBarra.SetSelected(0, true); //se deja seleccionado el primer items
                    lstProductosCodBarra.Focus(); //Se deja el foco sobre este control para que seleccione un items.
                }
            }

        }

        protected void lstProductosCodBarra_Leave(object sender, EventArgs e) //Oculta automáticamente el lstProductosCodBarra cuando el control pierde el foco.
        {
            this.lstProductosCodBarra.Enabled = false;
            this.lstProductosCodBarra.Visible = false;
            this.lstProductosCodBarra.Items.Clear();
        }



        protected void txtDescripcion_TextChanged(object sender, EventArgs e) //evento que se desencadena cuando cambia el valor del TextBox
        {
            if (this.estadoDelFormulario == "estEsperandoOperacion") //el proceso es capturado solo si está en este estado.
            {
                eventoBusDescripcion();
            }

        }

        protected void eventoBusDescripcion()
        {
            if (txtDescripcion.Text != "") //Si txtDescripcion es distinto de blanco se realiza el procesamiento. Esto se realiza para no perder el tiempo en filtro innecesarios.
            {
                if (refrescarResgProductos)   //si es necesario actualizar el resgProductos se lo hace sino no
                {
                    ejecutarHiloActualizarResgProductos();
                }

                ejecutarHiloFiltrarDescripcion();

                if (lstProductosDescripcion.Items.Count == 0)  //el filtro no obtuvo coincidencias, no se muestra el lstProductosDescripcion
                {
                    lstProductosDescripcion.Visible = false;
                    lstProductosDescripcion.Enabled = false;

                }
                else
                {
                    lstProductosDescripcion.Visible = true; //si se obtuvo una o más coincidencia se muestran en lstProductosDescripcion, y espera a que el usuario seleccione una.
                    lstProductosDescripcion.Enabled = true;

                }

            }
            else  //Si txtDescripcion es blanco no se realiza el procesamiento
            {
                lstProductosDescripcion.Enabled = false;
                lstProductosDescripcion.Visible = false;
            }
        }

        protected void ejecutarHiloFiltrarDescripcion()
        {
            if ((this.oHiloFiltrarDescripcion.ThreadState == ThreadState.Unstarted) || (this.oHiloFiltrarDescripcion.ThreadState == ThreadState.Stopped))
            {
                this.oHiloFiltrarDescripcion = new Thread(new ThreadStart(filtrarDescripcion)); //Instancia el hilo y lo delega al metodo filtrarDescripcion. 
                this.oHiloFiltrarDescripcion.Priority = ThreadPriority.AboveNormal;
                this.oHiloFiltrarDescripcion.Start();  //hilo que filtra las descripciones asociadas al valor del txtDescripcion y lo carga en lstProductosDescripcion
            }

        }


        protected void filtrarDescripcion()
        {
            //this.oHiloActualizarResgProductos.Join(); //espera a que primero termine el oHiloActualizarResgProductos para proceder con el actual.

            lstProductosDescripcion.Items.Clear(); //vaciamos el lstProductosDescripcion por si tuviera descripciones anteriores.

            try
            {
                foreach (Producto unProducto in resgProductos) //buscamos las descripciones que coinciden con (al menos una palabra o letra + txtDescripcion.text + ninguna o muchas palabras o letras) y la cargamos en el lstProductosDescripcion
                {

                    if (Regex.Match(unProducto.Descripcion, txtDescripcion.Text.Trim().ToUpper()).Success)
                    {
                        lstProductosDescripcion.Items.Add(unProducto.Descripcion);
                    }

                }
            }
            catch (InvalidExpressionException)
            {

            }

            catch (Exception)
            {
                txtDescripcion.Text = "";

            }

        }

        protected void txtDescripcion_KeyDown(object sender, KeyEventArgs e) //Método que captura el evento de presión de una tecla sobre txtDescripcion
        {
            if ((e.KeyCode == Keys.Down) & (lstProductosDescripcion.Items.Count > 0) & (estadoDelFormulario == "estEsperandoOperacion")) //Si se presiona para abajo y tiene a lstProductosDescripcion visible (es decir se encuentra esperando operacion y con items en la lista)
            {

                lstProductosDescripcion.SetSelected(0, true); //se deja seleccionado el primer items
                lstProductosDescripcion.Focus(); //Se deja el foco sobre este control para que seleccione un items.

            }
            
        }



        protected void lstProductosDescripcion_Leave(object sender, EventArgs e) //Oculta automáticamente el lstProductosDescripcion cuando el control pierde el foco.
        {
            this.lstProductosDescripcion.Enabled = false;
            this.lstProductosDescripcion.Visible = false;
        }

        protected void lstProductosDescripcion_DoubleClick(object sender, EventArgs e) //evento que captura la elección de un item en el lstProductosDescripcion
        {
            procesarEleccionLstProductosDescripcion();
        }


        protected void procesarEleccionLstProductosDescripcion()  //Se encapsula para que capture Double click y Enter sobre  lstProductosDescripcion
        {
            try
            {
                this.estadoDelFormulario = "Buscando";

                cargarProductoPorDescripcion(lstProductosDescripcion.SelectedItem.ToString()); //busca producto por descripción y lo carga en los textBox.

                estEsperandoOperacion(); //se deja en el estado necesario

            }
            catch (IndexOutOfRangeException)
            {

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }
        }

       

        

        protected void btnProcesar_Click(object sender, EventArgs e)
        {
            procesar();
        }

        
        protected void procesar() //se encapsulo en un método para usar cuando se presiona Enter con los textBox
        {
            
            if (formularioValido())
            {
                try
                {
                    DialogResult result = MessageBox.Show("¿Desea actualizar los precios de los productos en la grilla? ", "CONFIRMACION ACTUALIZACION DE PRECIO", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

                    if (result == DialogResult.Yes)
                    {

                        generarListaPrecios(); //crea el archivo y le añade los registro de precios para ser enviados a los post.

                        actualizarPreciosLocales(); //se actualizan los precios de la base de datos local.

                        //Se muestra un mje de confirmación.
                        MessageBox.Show("precios actualizados con exito!!!", "AVISO", MessageBoxButtons.OK, MessageBoxIcon.Information);

                        vaciarTextBox();

                        estEsperandoOperacion();
                    }
                }


                catch (IndexOutOfRangeException)
                {

                }
                catch (Exception ex)
                {
                    //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                    MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                    //Si llega a ocurrir algún error en estado agregar 
                    this.Close();
                }

            }
            else
            {
                informarExistenciaError();
            }
        }

        private bool formularioValido() //método realiza todas las operaraciones de validación
        {
            validarGrilla();

            if ((errorProvider1.GetError(dgvProductos) == ""))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private void validarGrilla() //recorre todo el dataGride y verifica que los datos se encuentren correctos, si alguno está incorrecto los pinta de blanco
        {
            if (dgvProductos.RowCount == 0) //si la grilla está vacia
            {
                errorProvider1.SetError(dgvProductos, "La grilla se encuentra vacia");

            }
            else
            {
                bool grillaSinError = true;  //inicializa el booleano que controla si el dgvProductos tiene al menos un error.

                foreach (DataGridViewRow row in dgvProductos.Rows)
                {
                    if (((new ValidarDatos().validarMoneda("Fila:", Convert.ToString(row.Cells[2].Value))) != "") || (new ValidarDatos().validarMoneda("Fila:", Convert.ToString(row.Cells[3].Value)) != ""))
                    {
                        grillaSinError = false;  //si la fila está tildada y tiene error en la cantidad o en kilo/ltrs se pone a falso
                    }


                }

                if (grillaSinError)
                {
                    errorProvider1.SetError(dgvProductos, "");
                }
                else
                {
                    errorProvider1.SetError(dgvProductos, "Algunos de los campos cantidad en la grilla no contiene datos válidos.");
                }

            }
            
        }

        private void generarListaPrecios()
        {

            ArrayList listaPost = new ArrayList(); //almacenara los nombres (string) de todos los post, para ser enviados la lista de precios.

            listaPost = obtenerNombresPost(); //se obtienen todos los nombre de post.
            foreach (string nombrePost in listaPost)
            {
                //guardar el archivo a través del objeto FileStream.
                try
                {
                    listaPreciosSalida = new FileStream("F:\\Dropbox\\" + nombrePost + "\\Datos del Sistema\\Lista de Precios\\Precios" + DateTime.Now.ToString("dMMyyyyHHmm") + ".cq", FileMode.OpenOrCreate, FileAccess.Write); //abre el archivo con acceso de escritura

                    CargarDatosAlArchivo();

                }

                catch (SerializationException)
                {
                    //notifica al usuario si el archivo no existe
                    MessageBox.Show("Error al escribir en el archivo", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                catch (FormatException)
                {
                    //notifica al usuario si el archivo no existe
                    MessageBox.Show("Formato inválido", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                catch (IOException)
                {
                    //notifica al usuario si el archivo no existe
                    MessageBox.Show("Error al abrir el archivo", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {
                    cerrarArchivo();
                }   
            }
            
        }

        private void CargarDatosAlArchivo()  //guarda los registros en el archivo.
        {
            RegistroListaPrecio unRegistroListaPrecio;

            unRegistroListaPrecio = new RegistroListaPrecio(obtenerFechaActual());

            aplicadorFormato.Serialize(listaPreciosSalida, unRegistroListaPrecio);
            
            foreach (DataGridViewRow row in dgvProductos.Rows)
            {
                RegistroProductoListaPrecio unRegistroProductoListaPrecio; //instanciamos un registroListaPrecio(Serializado) y le asignamos nombre.

                unRegistroProductoListaPrecio = new RegistroProductoListaPrecio(Convert.ToString(row.Cells[0].Value), Convert.ToString(row.Cells[1].Value), Convert.ToDouble(row.Cells[2].Value), Convert.ToDouble(row.Cells[3].Value), obtenerFechaActual());

                //escribe registro al objeto FileStream (serializa el objeto)
                aplicadorFormato.Serialize(listaPreciosSalida, unRegistroProductoListaPrecio);
            }


        }

        protected void btnBusDescripcion_Click(object sender, EventArgs e) //captura el evento Click sobre el boton btnBusDescripcion
        {
            eventoBusDescripcion();
        }

        protected void lstProductosCodBarra_KeyDown(object sender, KeyEventArgs e) //captura el evento keyDown cuando se presiona enter sobre lstProductosCodBarra
        {
            if (e.KeyCode == Keys.Enter)
            {
                procesarEleccionLstProductosCodBarra();
            }
            else
            {
                if ((e.KeyCode == Keys.Up) & (lstProductosCodBarra.SelectedIndex == 0))//si llega al primer lugar y presiona para arriba, vuelve al txtCodBarra
                {
                    txtCodBarra.Focus();
                }
            }
        }

        protected void lstProductosDescripcion_KeyDown(object sender, KeyEventArgs e) //captura el evento keyDown cuando se presiona enter sobre lstProductosDescripcion
        {
            if (e.KeyCode == Keys.Enter)
            {
                procesarEleccionLstProductosDescripcion();
            }
            else
            {
                if ((e.KeyCode == Keys.Up) & (lstProductosDescripcion.SelectedIndex == 0)) //si llega al primer lugar y presiona para arriba, vuelve al txtDescripcion
                {
                    txtDescripcion.Focus();
                }

            }
        }


        private string obtenerFechaActual()  //Dato necesario para el alta de venta
        {
            frmPlantillaPadre unFrm = (frmPlantillaPadre)this.MdiParent;
            return unFrm.getFechaActual();
        }

        private void txtCodBarra_TextChanged(object sender, EventArgs e)  //si se modifica txtCodBarra, se oculta lstCodBarra
        {
            lstProductosCodBarra.Visible = false;
            lstProductosCodBarra.Enabled = false;
        }

        protected virtual void frmActualizarPreciosCentral_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.F1)
            {

                bool tieneError = false;

                foreach (System.Windows.Forms.Control ctrl in this.Controls)
                {
                    if (errorProvider1.GetError(ctrl) != "")
                    {
                        tieneError = true;
                    }
                }

                if (tieneError) mostrarErrores();
            }
            else
            {
                if (e.KeyCode == Keys.F12)
                {
                    refrescarResgProductos = true;

                }
            }
        }

        private void cerrarArchivo()
        {
            try
            {
                if (listaPreciosSalida != null)  //determina si existe el archivo
                {
                    listaPreciosSalida.Close();  //cierra el archivo
                }
            }
            catch (IOException)  //notifica al usuario del error al cerrar el archivo
            {
                MessageBox.Show("No se puede cerrar el archivo.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

            }
        }

        private ArrayList obtenerNombresPost()
        {
            string[] listaSubcarpetas; //variable que almacenará la lista de todas las subcarpetas dentro de Dropbox.
            listaSubcarpetas = Directory.GetDirectories("F:\\Dropbox"); //obtenemos la lista de las subcarpetas en Dropbox.

            ArrayList nombresPost = new ArrayList(); //creamos un arrayList, que almacenará solo los nombre de los post
            nombresPost.Clear(); //vaciamos el arrayList

            foreach (string unaSubcarpeta in listaSubcarpetas) 
            {
                FileInfo unFileInfo = new FileInfo(unaSubcarpeta); //creamos un FileInfo que almacen
                if (Regex.Match(unFileInfo.Name, "POST*").Success)
                {
                    nombresPost.Add(unFileInfo.Name);
                }   
            }

            return (nombresPost);

        }

        private void actualizarPreciosLocales() //Se actualizan localmente los precios de los productos.
        {
            foreach (DataGridViewRow row in dgvProductos.Rows)
            {
                try
                {
                    productosTa.UpdateQueryPrecios(Math.Round(Convert.ToDecimal(row.Cells[2].Value), 2),Math.Round(Convert.ToDecimal(row.Cells[3].Value), 2),Convert.ToDateTime(obtenerFechaActual()), row.Cells[1].Value.ToString()); //se busca el producto por nombre.

                    /*se cambia el precioCosto, precioVenta y fechaActualización de cada producto en la grilla.
                    centerQuimDs.Productos[0].precioCosto = Math.Round(Convert.ToDouble(row.Cells[2].Value), 2);
                    centerQuimDs.Productos[0].precioVenta = Math.Round(Convert.ToDouble(row.Cells[3].Value), 2);
                    centerQuimDs.Productos[0].fechaActualización = Convert.ToDateTime(obtenerFechaActual());

                    productosTa.Update (centerQuimDs.Productos); //se actualiza el precio del producto.*/

                }
                catch (Exception)
                {
                    
                }
                

            }

        }


    }
}